/**
 * @file app_button.c
 * @brief 按键驱动实现
 * @date 2025-11-17
 */

#include "app_button.h"
#include "user_config.h"

// 按键状态标志位
static uint8_t s_button_ignore1_pressed = 0;      // "忽略1"按键按下标志
static uint8_t s_button_ignore2_pressed = 0;      // "忽略2"按键按下标志
static uint8_t s_button_replace_pressed = 0;      // "更换成功"按键按下标志

// 按键中断待确认标志(防抖用)
static uint8_t s_button_ignore1_pending = 0;
static uint8_t s_button_ignore2_pending = 0;
static uint8_t s_button_replace_pending = 0;

// 按键防抖计时器
static uint32_t s_button_ignore1_debounce_timer = 0;
static uint32_t s_button_ignore2_debounce_timer = 0;
static uint32_t s_button_replace_debounce_timer = 0;

/**
 * @brief 按键GPIO初始化
 */
static void button_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(BUTTON_IGNORE1_GPIO_RCC | BUTTON_IGNORE2_GPIO_RCC |
                           BUTTON_REPLACE_GPIO_RCC | RCC_APB2Periph_AFIO, ENABLE);

    // 配置PB13 - "忽略1"按键
    GPIO_InitStructure.GPIO_Pin = BUTTON_IGNORE1_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;       // 上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(BUTTON_IGNORE1_GPIO_PORT, &GPIO_InitStructure);

    // 配置PB14 - "忽略2"按键
    GPIO_InitStructure.GPIO_Pin = BUTTON_IGNORE2_GPIO_PIN;
    GPIO_Init(BUTTON_IGNORE2_GPIO_PORT, &GPIO_InitStructure);

    // 配置PC3 - "更换成功"按键
    GPIO_InitStructure.GPIO_Pin = BUTTON_REPLACE_GPIO_PIN;
    GPIO_Init(BUTTON_REPLACE_GPIO_PORT, &GPIO_InitStructure);
}

/**
 * @brief 按键外部中断初始化
 */
static void button_exti_init(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 配置PB13 EXTI13
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource13);
    EXTI_InitStructure.EXTI_Line = BUTTON_IGNORE1_EXTI_LINE;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     // 下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    // 配置PB14 EXTI14
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
    EXTI_InitStructure.EXTI_Line = BUTTON_IGNORE2_EXTI_LINE;
    EXTI_Init(&EXTI_InitStructure);

    // 配置PC3 EXTI3
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);
    EXTI_InitStructure.EXTI_Line = BUTTON_REPLACE_EXTI_LINE;
    EXTI_Init(&EXTI_InitStructure);

    // 配置NVIC - EXTI15_10中断(PB13, PB14)
    NVIC_InitStructure.NVIC_IRQChannel = BUTTON_IGNORE1_EXTI_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 配置NVIC - EXTI3中断(PC3)
    NVIC_InitStructure.NVIC_IRQChannel = BUTTON_REPLACE_EXTI_IRQn;
    NVIC_Init(&NVIC_InitStructure);
}

/**
 * @brief 按键初始化
 */
void app_button_init(void)
{
    button_gpio_init();
    button_exti_init();

    // 初始化标志位
    s_button_ignore1_pressed = 0;
    s_button_ignore2_pressed = 0;
    s_button_replace_pressed = 0;

    s_button_ignore1_pending = 0;
    s_button_ignore2_pending = 0;
    s_button_replace_pending = 0;

    s_button_ignore1_debounce_timer = 0;
    s_button_ignore2_debounce_timer = 0;
    s_button_replace_debounce_timer = 0;
}

/**
 * @brief 读取"忽略1"按键状态
 */
uint8_t app_button_get_ignore1(void)
{
    uint8_t result = s_button_ignore1_pressed;
    s_button_ignore1_pressed = 0;       // 读取后清除
    return result;
}

/**
 * @brief 读取"忽略2"按键状态
 */
uint8_t app_button_get_ignore2(void)
{
    uint8_t result = s_button_ignore2_pressed;
    s_button_ignore2_pressed = 0;       // 读取后清除
    return result;
}

/**
 * @brief 读取"更换成功"按键状态
 */
uint8_t app_button_get_replace(void)
{
    uint8_t result = s_button_replace_pressed;
    s_button_replace_pressed = 0;       // 读取后清除
    return result;
}

/**
 * @brief 按键扫描任务(100ms调用一次)
 */
void app_button_scan(void)
{
    extern uint32_t DateUp_Time;    // 系统时间戳(ms)

    // "忽略1"按键防抖处理
    if(s_button_ignore1_pending)
    {
        if((DateUp_Time - s_button_ignore1_debounce_timer) >= BUTTON_DEBOUNCE_TIME_MS)
        {
            // 50ms后再次确认
            if(GPIO_ReadInputDataBit(BUTTON_IGNORE1_GPIO_PORT, BUTTON_IGNORE1_GPIO_PIN) == 0)
            {
                s_button_ignore1_pressed = 1;       // 确认有效按下
            }
            s_button_ignore1_pending = 0;           // 清除待确认标志
        }
    }

    // "忽略2"按键防抖处理
    if(s_button_ignore2_pending)
    {
        if((DateUp_Time - s_button_ignore2_debounce_timer) >= BUTTON_DEBOUNCE_TIME_MS)
        {
            if(GPIO_ReadInputDataBit(BUTTON_IGNORE2_GPIO_PORT, BUTTON_IGNORE2_GPIO_PIN) == 0)
            {
                s_button_ignore2_pressed = 1;
            }
            s_button_ignore2_pending = 0;
        }
    }

    // "更换成功"按键防抖处理
    if(s_button_replace_pending)
    {
        if((DateUp_Time - s_button_replace_debounce_timer) >= BUTTON_DEBOUNCE_TIME_MS)
        {
            if(GPIO_ReadInputDataBit(BUTTON_REPLACE_GPIO_PORT, BUTTON_REPLACE_GPIO_PIN) == 0)
            {
                s_button_replace_pressed = 1;
            }
            s_button_replace_pending = 0;
        }
    }
}

/**
 * @brief EXTI15_10中断服务函数 (PB13, PB14)
 */
void EXTI15_10_IRQHandler(void)
{
    extern uint32_t DateUp_Time;

    // PB13 - "忽略1"按键中断
    if(EXTI_GetITStatus(BUTTON_IGNORE1_EXTI_LINE) != RESET)
    {
        if(!s_button_ignore1_pending)
        {
            s_button_ignore1_pending = 1;
            s_button_ignore1_debounce_timer = DateUp_Time;
        }
        EXTI_ClearITPendingBit(BUTTON_IGNORE1_EXTI_LINE);
    }

    // PB14 - "忽略2"按键中断
    if(EXTI_GetITStatus(BUTTON_IGNORE2_EXTI_LINE) != RESET)
    {
        if(!s_button_ignore2_pending)
        {
            s_button_ignore2_pending = 1;
            s_button_ignore2_debounce_timer = DateUp_Time;
        }
        EXTI_ClearITPendingBit(BUTTON_IGNORE2_EXTI_LINE);
    }
}

/**
 * @brief EXTI3中断服务函数 (PC3)
 */
void EXTI3_IRQHandler(void)
{
    extern uint32_t DateUp_Time;

    if(EXTI_GetITStatus(BUTTON_REPLACE_EXTI_LINE) != RESET)
    {
        if(!s_button_replace_pending)
        {
            s_button_replace_pending = 1;
            s_button_replace_debounce_timer = DateUp_Time;
        }
        EXTI_ClearITPendingBit(BUTTON_REPLACE_EXTI_LINE);
    }
}
